package net.asfun.jvalog.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.logging.Level;

import javax.script.Bindings;

import static net.asfun.jvalog.misc.Log.logger;
import net.asfun.jvalog.domain.Category;
import net.asfun.jvalog.domain.Page;
import net.asfun.jvalog.domain.Post;
import net.asfun.jvalog.domain.Tag;
import net.asfun.jvalog.except.ViewException;
import net.asfun.jvalog.misc.Setting;
import net.asfun.jvalog.misc.StringUtil;
import net.asfun.jvalog.view.PagerInfo;
import net.asfun.jvalog.view.SiteInfo;
import net.asfun.template.Configuration;
import net.asfun.template.Template;
import net.asfun.template.TemplateException;
import net.asfun.template.bin.LazyBindings;

public class Painter {
	
	private static Template template;
	private static Configuration templateConfig;
	private static LazyBindings common = new LazyBindings();
	
	static {
		Map<String,String> lazies = new HashMap<String,String>();
		lazies.put("categories", "net.asfun.jvalog.misc.AutoLoader.getCategories");
		lazies.put("comments", "net.asfun.jvalog.misc.AutoLoader.getComments");
		lazies.put("blogroll", "net.asfun.jvalog.misc.AutoLoader.getLinks");
		lazies.put("recentPosts", "net.asfun.jvalog.misc.AutoLoader.getPosts");
		lazies.put("archives", "net.asfun.jvalog.misc.AutoLoader.getArchives");
		common.config(lazies);
		templateConfig = Configuration.getDefaultConfig();
//		Configuration.addImport(clazz);
		reset();
	}
	
	public static void reset() {
		templateConfig.setTemplateRoot(
			Setting.root + "/themes/" + SiteInfo.getInstance().getTheme() + "/");
		templateConfig.setTimezone(TimeZone.getTimeZone(Setting.getTimezone()));
		template = new Template(templateConfig);
		common.put("site", SiteInfo.getInstance());
		template.setCommonBindings(common);
	}
	
	private Painter(){}
	
	public static String render(String tpl, Bindings data) {
		try {
			return template.render(tpl, data);
		} catch (TemplateException e) {
			logger.log(Level.SEVERE, e.getMessage(), e.getCause());
			throw new ViewException("Can't render template " + tpl);
		}
	}
	
	public static String index(int page) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		//posts
		PagerInfo pager = new PagerInfo();
		pager.setIndex(page);
		data.put("posts", Post.listPublished(pager));
		data.put("pager", pager);
		return render("index.html", data);
	}

	public static String rss() {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("posts", Post.listRecent(Setting.getRssSize()));
		return render("rss.xml", data);
	}

	public static String atom() {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("posts", Post.listRecent(Setting.getAtomSize()));
		return render("atom.xml", data);
	}

	public static String sitemap() {
		List<HashMap<String,Object>> urlset = new ArrayList<HashMap<String,Object>>();
		HashMap<String,Object> main = new HashMap<String,Object>();
		main.put("location", SiteInfo.getInstance().getUrl());
		main.put("lastmod",new Date());
		main.put("changefreq", "daily");
		main.put("priority", 0.9);
		urlset.add(main);
		List<Page> pages = Page.listPublished();
		for(Page page : pages) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", page.getLink());
			url.put("lastmod", page.getDate());
			url.put("changefreq", "monthly");
			url.put("priority", 0.8);
			urlset.add(url);
		}
		List<Post> posts = Post.listRecent(Setting.getMapSize());
		for(Post post : posts) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", post.getLink());
			url.put("lastmod", post.getDate());
			url.put("changefreq", "never");
			url.put("priority", 0.7);
			urlset.add(url);
		}
		List<Category> cates = Category.listAll();
		for(Category cate : cates) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", cate.getLink());
			url.put("changefreq", "weekly");
			url.put("priority", 0.5);
			urlset.add(url);
		}
		List<Tag> tags = Tag.listAll();
		for(Tag tag : tags) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", tag.getLink());
			url.put("changefreq", "weekly");
			url.put("priority", 0.4);
			urlset.add(url);
		}
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("urlset", urlset);
		return render("sitemap.xml", data);
	}

	public static String tag() {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("tags", Tag.listAll());
		return render("tags.html", data);
	}
	
	public static String category() {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		// TODO 
//		data.put("categories", Category.tree());
		return render("categories.html", data);
	}

	public static String media(String name) {
		// TODO
//		return Media.content(name);
		return "";
	}

	public static String date(String[] ymd, int page) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("title", StringUtil.join(ymd,"-"));
		PagerInfo pager = new PagerInfo();
		pager.setIndex(page);
		data.put("posts", Post.listArchive(ymd, pager));
		data.put("pager", pager);
		return render("date.html", data);
	}
	
	public static String tag(String slogan, int page) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		Tag tag = Tag.load(slogan);
		data.put("tag", tag);
		//posts
		PagerInfo pager = new PagerInfo();
		pager.setIndex(page);
		data.put("posts", tag.listPublishedPosts(pager));
		data.put("pager", pager);
		return render("tag.html", data);
	}
	
	public static String category(String slogan, int page) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		Category cate = Category.load(slogan);
		data.put("category", cate);
		//posts
		PagerInfo pager = new PagerInfo();
		pager.setIndex(page);
		data.put("posts", cate.listPublishedPosts(pager));
		data.put("pager", pager);
		return render("category.html", data);
	}
	
	public static String post(String uri) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("post", Post.load(uri));
		return render("post.html", data);
	}

	public static String error(String code) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		return render(code + ".html", data);
	}

	public static String page(String uri) {
		Bindings data = template.createBindings(Template.NORMBINDINGS);
		data.put("page", Page.load(uri));
		return render("page.html", data);
	}
}
